<?php

declare(strict_types=1);
/*
 * @Description: 微信公众平台service类
 * @Author: QianLong
 * @Date: 2019-10-13 12:39:05
 * @LastEditors    : QianLong
 * @LastEditTime   : 2024-05-15 11:35:10
 */

namespace App\Service;

use App\Common\RedisCache;
use App\Exception\ApiException;
use App\Service\Weixin\Prpcrypt;
use Yurun\Util\HttpRequest;
use Hyperf\Di\Annotation\Inject;
class MpWeixin
{
    #[Inject]
    protected RedisCache $redisCache;

    public function getAllMedia($mw_id, $type, $offset)
    {
        $infoData = $this->redisCache->getMpWxInfo($mw_id);
        $accessToken = $this->redisCache->getWechatAccessToken($infoData['app_id'], $infoData['app_secret']);
        $url = 'https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=' . $accessToken;
        $http = new HttpRequest;
        $post['type'] = $type;
        $post['offset'] = $offset;
        $post['count'] = 20;
        $response = $http->post($url, $post, 'json');
        return json_decode($response->body(), true);
    }
    public function uploadMedia($mw_id, $type, $media, $title = '', $introduction = '')
    {
        $infoData = $this->redisCache->getMpWxInfo($mw_id);
        $accessToken = $this->redisCache->getWechatAccessToken($infoData['app_id'], $infoData['app_secret']);
        $url = 'https://api.weixin.qq.com/cgi-bin/media/add_material?access_token=' . $accessToken;
        $http = new HttpRequest;
        $post['access_token'] = $accessToken;
        $post['type'] = $type;
        $post['media'] = $media;
        if ($type == 'video') {
            $post['description']['title'] = $title;
            $post['description']['introduction'] = $introduction;
        }
        $response = $http->post($url, $post);
        return json_decode($response->body(), true);
    }
    public function createMenu($mw_id, $post = [])
    {
        $infoData = $this->redisCache->getMpWxInfo($mw_id);
        $accessToken = $this->redisCache->getWechatAccessToken($infoData['app_id'], $infoData['app_secret']);
        $url = 'https://api.weixin.qq.com/cgi-bin/menu/create?access_token=' . $accessToken;
        $http = new HttpRequest;
        $post = (is_array($post))? $post:json_decode($post,true);
        $post['access_token'] = $accessToken;
        $response = $http->post($url, $post,'json');
        return json_decode($response->body(), true);
    }
    public function sendTemplateMsg($mw_id, $touser, $template_id, $data = '', $urlLink = '', $miniprogram='')
    {
        $infoData = $this->redisCache->getMpWxInfo($mw_id);
        $accessToken = $this->redisCache->getWechatAccessToken($infoData['app_id'], $infoData['app_secret']);
        $url = 'https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=' . $accessToken;
        $http = new HttpRequest;
        $post['access_token'] = $accessToken;
        $post['touser'] = $touser;
        $post['template_id'] = $template_id;
        $data = is_array($data)? $data:json_decode($data,true);
        $buildData = [];
        foreach ($data as $key => $vo) {
            if (is_array($vo)) {
                $buildData[$key]['value'] = $vo[0];
                $buildData[$key]['color'] = $vo[1];
            }else{
                $buildData[$key]['value'] = $vo;
            }
        }
        $post['data'] = $buildData;
        if (!empty($urlLink)) {
            $post['url'] = $urlLink;
        }
        if (!empty($miniprogram)) {
            $miniprogram = is_array($miniprogram) ? $miniprogram : json_decode($miniprogram, true);
            $post['miniprogram'] = $miniprogram;
        }
        $response = $http->post($url, $post,'json');
        return json_decode($response->body(), true);
    }
    public function sendKfMsg($mw_id, $touser, $msg_type, $data = '')
    {
        $infoData = $this->redisCache->getMpWxInfo($mw_id);
        $accessToken = $this->redisCache->getWechatAccessToken($infoData['app_id'], $infoData['app_secret']);
        $url = 'https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=' . $accessToken;
        $http = new HttpRequest;
        $post['access_token'] = $accessToken;
        $post['touser'] = $touser;
        $post['msgtype'] = $msg_type;
        $data = is_array($data)? $data:json_decode($data,true);
        $post[$msg_type] = $data;
        $response = $http->post($url, json_encode($post,JSON_UNESCAPED_UNICODE),'json');
        return json_decode($response->body(), true);
    }
    public function getQrcode($mw_id, $param)
    {
        $infoData = $this->redisCache->getMpWxInfo($mw_id);
        $accessToken = $this->redisCache->getWechatAccessToken($infoData['app_id'], $infoData['app_secret']);
        $url = 'https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=' . $accessToken;
        $http = new HttpRequest;
        $post['access_token'] = $accessToken;
        $post['action_name'] = $param['action_name'];
        if (!empty($param['expire_seconds'])) {
            $post['expire_seconds'] = $param['expire_seconds'];
        }
        if (!empty($param['scene_id'])) {
            $post['action_info']['scene']['scene_id'] = $param['scene_id'];
        }
        if (!empty($param['scene_str'])) {
            $post['action_info']['scene']['scene_str'] = $param['scene_str'];
        }
        $response = $http->post($url, $post, 'json');
        return json_decode($response->body(), true);
    }
    /**
     * sign校验
     */
    public function checkSignature($paramData, $token)
    {
        $tmpStr = $this->generalSign($paramData['timestamp'], $paramData['nonce'], $token);
        if ($tmpStr != $paramData['signature']) {
            throw new ApiException(-1, 'signature校验失败');
        }
    }
    public function generalSign($timestamp, $nonce, $token)
    {
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode($tmpArr);
        $tmpStr = sha1($tmpStr);
        return $tmpStr;
    }
    public function generalWxReply($arr, $isEncrypt = false, $token = '', $aes = '', $appId = '')
    {
        if ($isEncrypt) {
            $arr['CreateTime'] = (!isset($arr['CreateTime'])) ? time() : $arr['CreateTime'];
            $xmlStr = $this->arrayToXml($arr);
            $pc = new Prpcrypt($aes);
            $encryptData = $pc->encrypt($xmlStr, $appId);
            if ($encryptData[0] != 0) {
                return '';
            }
            $arrEncrypt['Encrypt'] = $encryptData[1];
            $arrEncrypt['TimeStamp'] = time();
            $arrEncrypt['Nonce'] = createId();
            $arrEncrypt['MsgSignature'] = $this->generalSign($arrEncrypt['TimeStamp'], $arrEncrypt['Nonce'], $token);
            $arrEncrypt['ToUserName'] = $arr['ToUserName'];
            $arrEncrypt['FromUserName'] = $arr['FromUserName'];
            $arrEncrypt['EncryptType'] = 'aes';
            return $this->arrayToXml($arrEncrypt);
        } else {
            $arr['CreateTime'] = (!isset($arr['CreateTime'])) ? time() : $arr['CreateTime'];
            return $this->arrayToXml($arr);
        }
    }
    public function arrayToXml($arr, $root = true)
    {
        $xml = '';
        if ($root) {
            $xml .= "<xml>";
        }
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                if (is_array($val)) {
                    $child = $this->arrayToXml($val, false);
                    $xml .= "<" . $key . ">".$child."</" . $key . ">";
                } else {
                    $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
                }
            }
        }
        if ($root) {
            $xml .= "</xml>";
        }
        return $xml;
    }
}
